home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Printer Drivers… / LaserWriterIIsc (New GX v1.1) / LaserSCIntf.c < prev    next >
Encoding:
Text File  |  1996-03-20  |  31.8 KB  |  991 lines  |  [TEXT/MPS ]

  1. /*----------------------------------------------------------------------------------------------
  2. FILENAME
  3.  
  4.     LaserSCIntf.c
  5.     
  6. DESCRIPTION
  7.  
  8.     This file contains routines for invoking commands within the command set provided by the 
  9.     LaserWriter SC and IISC. Routines within this file utilize the WriteData and CheckStatus
  10.     printing messages to in order to communicate with the printer. The actual SCSI code used to
  11.     perform the I/O to the printer is implemented in the SD_WriteData, SD_CheckStatus and
  12.     SD_GetDeviceStatus routines within the UniversalMessageIntf.c file.  The routines in this 
  13.     file provide a "higher level" interface to the SC/IISC by hiding the details of the SC/IISC 
  14.     commands and their implementation. 
  15.  
  16. COPYRIGHT
  17.  
  18.     Copyright Apple Computer, Inc.  1989-1992
  19.     All rights reserved.
  20.     
  21. ROUTINES IN THIS MODULE:
  22.  
  23.     interface routines:
  24.         LaserSC_OpenConn()
  25.         LaserSC_GetDeviceStatus()
  26.         LaserSC_ResetDevice()
  27.         LaserSC_GetSenseData()
  28.         LaserSC_SetPageMargins()
  29.         LaserSC_SetPageDimensions()
  30.         LaserSC_ClearBits()
  31.         LaserSC_DrawBits()
  32.         LaserSC_PrintPage()
  33.         LaserSC_QueryPrinter()
  34.         LaserSC_SetBuffandFeedMode()
  35.         LaserSC_GetTimeoutForSCSICmnd()
  36.  
  37.     
  38. -----------------------------------------------------------------------------------------------*/
  39.  
  40. // Include the standard Mac header files 
  41. #include "MacIncludes.h"
  42.  
  43. // Include the new QuickDraw GX graphics header files 
  44. #include <GXGraphics.h>
  45. #include <GraphicsLibraries.h>
  46. #include <GXMath.h>
  47.  
  48. // Include the required Printing Manager header files 
  49. #include <GXPrinting.h>
  50. #include <GXPrinterDrivers.h>
  51. #include <Collections.h>
  52. #include <GXMessages.h>
  53.  
  54. #include <GXExceptions.h>
  55.  
  56. // Include the internal driver constants and types used by this module 
  57. #include "LaserSCResources.h"
  58. #include "UniversalMessageIntf.h"
  59. #include "LaserSCIntf.h"
  60.  
  61.  
  62. /*********************************************************************************
  63.  *                                         CONSTANTS                                                     *
  64.  *********************************************************************************/
  65.  
  66. // Miscellaneous constants
  67. enum
  68. {
  69.     minSCSICmndSz            = 5,            // Min. # of inquiry bytes returned by all SCSI devices
  70.  
  71.     kMaxRowBytes            = 304,        // max rowBytes supported by SC printer
  72.  
  73.     kPrintFromSCRam        = 0x0080,    //    Bit in the SCSI Print page command that sets the "print from printer RAM" attribute
  74.     kPrintContinuous        = 0x0040,    //    Bit in the SCSI Print page command that sets the "print a 8 ppm rate" attribute
  75.     kClearWhilePrinting    = 0x0020,    //    Bit in the SCSI Print page command that sets the "clear page while page is being printed" attribute
  76.  
  77.     kBuffered                = 2,            // These constants are used to set the manual feed and buffered mode of the printer
  78.     kFeed                        = 4,
  79.     kManual                    = 0x01,
  80.     kBufferedMode            = 0x10
  81. };
  82.  
  83.  
  84. /*********************************************************************************
  85.  *                                         TYPES                                                         *
  86.  *********************************************************************************/
  87.  
  88. // SCSICommData - structure that defines the layout of the SCSI version of the 'comm' resource
  89.  
  90. typedef struct
  91. {
  92.     ResType                commType;                // communications type ('sPTL')
  93.     
  94.     ProcPtr                releaseDevice;            // Pointer to C routine that can release SCSI device,
  95.                                                         // can be nil (N/A for this driver)
  96.     short                    scsiIOAttributes;        // SCSI I/O attributes applicable to data xfers (N/A for this driver)
  97.     short                    *statusByte;            // Location to store status byte from data xfer operation,
  98.                                                         // can be nil (N/A for this driver)
  99.     short                    scsiBus;                    // Number of scsi bus to which device is attached (0 = motherboard; applies to open connection call only). (N/A for this driver)
  100.     short                    deviceNum;                // Number of scsi device to open connection to (applies to open connection call only). (N/A for this driver)
  101.     long                    bytesPerChunk;            // 0 => ignored; > 0 => break data transfer into chunks
  102.                                                         // of this size (at SCSI TIB level). (N/A for this driver)
  103.     ProcPtr                acquireDevice;            // Pointer to C routine that can acquire SCSI device,
  104.                                                         // nil == use info below in standard routine (N/A for this driver)
  105.     short                    deviceKind;                // device kind to look for in reponse
  106.     short                    minLength;                // minimum additional data to get in response
  107.     short                    offsetStart;            // offset from start of returned data to look at (N/A for this driver)
  108.     Str255                searchString;            // string to search for in the response
  109. }    SCSICommData,
  110.     *SCSICommDataPtr,
  111.     **SCSICommDataHdl;
  112.  
  113.  
  114. /*********************************************************************************
  115.  *                                         DEFINES                                                         *
  116.  *********************************************************************************/
  117.  
  118. // Useful defines for doing I/O to the printer
  119.  
  120. #define    SendSCSICmnd(pCmnd, cmndSize)                                        Send_GXWriteData(pCmnd, cmndSize)
  121. #define    GetDataFromPrinter(inputBuff, numToGet, scsiChunkSize)    Send_GXGetDeviceStatus(nil, scsiChunkSize, inputBuff, numToGet, "\p")
  122. #define    SendDataToPrinter(outputBuff, numToSend, scsiChunkSize)    Send_GXCheckStatus(outputBuff, numToSend, scsiChunkSize, kDrvrCreatorType)
  123. #define    GetLastSCSIStatus(lastStatus)                                        Send_GXGetDeviceStatus(nil, 0, nil, lastStatus, "\p")
  124.  
  125.  
  126. /***************************************************************************************
  127. *                                         INTERNAL ROUTINES                                                     *
  128. ***************************************************************************************/                        
  129.  
  130. /********************************************************************************************
  131.  
  132.                                         EqlByteStream
  133.     function:
  134.                 EqlByteStream compares two byte streams, for a specified number of characters, to 
  135.                 determine if they are equal. 
  136.     
  137.     parameters:
  138.                 stream1                    Pointer to first byte stream
  139.                 stream2                    Pointer to second byte stream
  140.                 bytesToChk                Number of bytes to compare in the two streams
  141.     
  142.     returns:
  143.                 EqlByteStream            Returns true if byte strings equal; false otherwise
  144.                     
  145. ********************************************************************************************/
  146. Boolean EqlByteStream(Ptr stream1, Ptr stream2, short bytesToChk)
  147. {
  148.     Boolean    theyMatch = true;
  149.     
  150.     // Assume streams will match initially
  151.     
  152.     for (; bytesToChk > 0; --bytesToChk)
  153.     {
  154.         if (*stream1++ != *stream2++)    // T => Streams don't match
  155.         {
  156.             theyMatch = false;
  157.             break;
  158.         }
  159.     }
  160.     
  161.     return(theyMatch);
  162. }
  163. /* EqlByteStream */
  164.  
  165.  
  166. /********************************************************************************************
  167.  
  168.                                         DeviceIsSCPrinter
  169.     function:
  170.                 DeviceIsSCPrinter queries the specified SCSI device to determine if it's a
  171.                 SC/IISC printer. If is, it returns true; otherwise it returns false.  The
  172.                 device to query is specified by the 
  173.     
  174.     parameters:
  175.                 scsiCommData    Handle to the 'comm' resource in the target DTP file
  176.     
  177.     returns:
  178.                 Boolean            Returns true if selected device is a SC/IISC printer; false otherwise
  179.                     
  180. ********************************************************************************************/
  181. Boolean DeviceIsSCPrinter(SCSICommDataHdl scsiCommData)
  182. {
  183.     OSErr                    anErr;
  184.     SCInquiryData        queryData;
  185.     Boolean                isOurPrinter = false;
  186.     short                    amntInqData;
  187.     
  188.     // Query the device to determine if it's a printer
  189.     
  190.     anErr = LaserSC_QueryPrinter(&queryData, minSCSICmndSz);
  191.     require(anErr == noErr, QueryPrinterFails1);
  192.     
  193.     // Device responded. Now see how much more data we can read from the device
  194.     
  195.     amntInqData = queryData.additionalLength + minSCSICmndSz;
  196.     if (amntInqData > sizeof(SCInquiryData)) // T => Only read max. bytes query record can hold
  197.         amntInqData = sizeof(SCInquiryData);
  198.         
  199.     // Now read as much of the query data as we can from the device
  200.     
  201.     anErr = LaserSC_QueryPrinter(&queryData, amntInqData);
  202.     require(anErr == noErr, QueryPrinterFails2);
  203.  
  204.     // Finally we can determine if the device is an SC/IISC
  205.     {
  206.         SCSICommDataPtr    pCommData = *scsiCommData;
  207.         
  208.         if (queryData.peripheralType == pCommData->deviceKind)    // T => Responding device is a printer
  209.         {
  210.             if (queryData.additionalLength >= pCommData->minLength)    // T => Device gave us enough additional query data
  211.             {
  212.                 // Do the device product names match? 
  213.                 isOurPrinter = EqlByteStream(    ((Ptr) &queryData) + pCommData->offsetStart, 
  214.                                                         (Ptr)(&pCommData->searchString[1]), 
  215.                                                         pCommData->searchString[0]);
  216.             }
  217.         }
  218.     }
  219.     
  220.     
  221. /******* Clean-up *******/
  222.  
  223. QueryPrinterFails2:
  224. QueryPrinterFails1:
  225.     return(isOurPrinter);
  226. }
  227. /* DeviceIsSCPrinter */
  228.  
  229.  
  230. /***************************************************************************************
  231. *                                         INTERFACE ROUTINES                                                     *
  232. ***************************************************************************************/                        
  233.  
  234. /********************************************************************************************
  235.  
  236.                                         LaserSC_OpenConnection
  237.     function:
  238.                 This routine establishes a connection to the LaserWriter SC/IISC referenced 
  239.                 in the current Job.  To determine which SCSI device number to use, we 
  240.                 extract the 'comm' resource from the target Desktop Printer file and use
  241.                 the deviceNum field in the SCSICommData handle that is returned.
  242.                 
  243.                 If LaserSC_OpenConnection is successful, the client should always call 
  244.                 LaserSC_SetPageMargins and LaserSC_SetPageDimensions to ensure the printer's 
  245.                 page buffer is properly initialized. Failure to call these routines could 
  246.                 reduce the life of the printing engine.
  247.  
  248.     parameters:
  249.                 None
  250.                     
  251.     returns:
  252.                 OSErr
  253.                     
  254. ********************************************************************************************/
  255. OSErr LaserSC_OpenConnection()
  256. {
  257.     OSErr                    anErr;
  258.     SpecGlobalsHdl     hGlobals = GetMessageHandlerInstanceContext();
  259.     Str31                    printerName;
  260.     SCSICommDataHdl    scsiCommData;
  261.  
  262.     // Get the name of the target desktop printer
  263.     
  264.     GXGetPrinterName(GXGetJobOutputPrinter(GXGetJob()), printerName);
  265.     
  266.     // Now extract the SCSI 'comm' resource to get at the device number
  267.     
  268.     anErr = GXFetchDTPData(printerName, gxDeviceCommunicationsType, gxDeviceCommunicationsID, (Handle *) &scsiCommData);
  269.     require(anErr == noErr, FetchDTPData);
  270.     
  271.     // Set the deviceNum field in the globals to be the device we want to access
  272.     (*hGlobals)->deviceNum = (*scsiCommData)->deviceNum;
  273.     
  274.     // Is the target device a LaserWriter SC/IISC printer?
  275.     if ( !DeviceIsSCPrinter(scsiCommData) )
  276.         anErr = gxAioCantFindDevice;
  277.  
  278.     // Dump the resource handle we fetched
  279.     DisposeHandle((Handle) scsiCommData);
  280.     
  281.     check(anErr == noErr);
  282.  
  283.     
  284. /******* Clean-up *******/
  285.  
  286. FetchDTPData:
  287.     return(anErr);
  288. }
  289. /* LaserSC_OpenConnection */
  290.  
  291.  
  292. /********************************************************************************************
  293.  
  294.                                         LaserSC_GetDeviceStatus
  295.     function:
  296.                 LaserSC_GetDeviceStatus queries the printer to determine if it's ready to print.
  297.                 It returns a deviceStatus parameter which indicates the current readiness state of
  298.                 the device (kGoodCondition, kCheckCondition, or kBusy). If the device is in a
  299.                 check condition state, the client can call LaserSC_GetSenseData to determine the 
  300.                 exact reason why the device isn't ready.
  301.  
  302.     parameters:
  303.                 deviceStatus        Returns the current status of the device
  304.     
  305.     returns:
  306.                 OSErr
  307.                     
  308. ********************************************************************************************/
  309. OSErr LaserSC_GetDeviceStatus(short *deviceStatus)
  310. {
  311.     OSErr            anErr;
  312.     short            scsiCommand[3];
  313.     long            cmndSz;
  314.     long            lastStatus;
  315.     
  316.     // Set up the test for ready SCSI command to be sent to the printer
  317.     
  318.     scsiCommand[0] = kSCPrinterReady;
  319.     scsiCommand[1] = kSCReserved;
  320.     scsiCommand[2] = kSCReserved;
  321.     cmndSz             = 6;
  322.     
  323.     // Send the SCSI command to the device
  324.     
  325.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  326.     require(anErr == noErr, SendSCSICmndFails);
  327.     
  328.     // Now fetch the last status of the device
  329.     
  330.     anErr = GetLastSCSIStatus(&lastStatus);
  331.     require(anErr == noErr, GetLastSCSIStatusFails);
  332.     
  333.     // Return the last status
  334.     *deviceStatus = lastStatus;
  335.         
  336.  
  337. /******* Clean-up *******/
  338.  
  339. GetLastSCSIStatusFails:
  340. SendSCSICmndFails:
  341.     return(anErr);
  342. }
  343. /* LaserSC_GetDeviceStatus */
  344.  
  345.  
  346. /********************************************************************************************
  347.  
  348.                                         LaserSC_ResetDevice
  349.     function:
  350.                 LaserSC_ResetDevice will reset the LaserWriter SC/IISC to its default power-up
  351.                 state (without performing the power-up diagnostics).
  352.                     
  353.     parameters:
  354.                 none    
  355.                 
  356.     returns:
  357.                 OSErr
  358.                     
  359. ********************************************************************************************/
  360. OSErr LaserSC_ResetDevice()
  361. {
  362.     OSErr        anErr;
  363.     short        scsiCommand[3];
  364.     long        cmndSz;
  365.     
  366.     // Set up the reset SCSI command to be sent to the printer
  367.     
  368.     scsiCommand[0] = kSCResetPrinter;
  369.     scsiCommand[1] = kSCReserved;
  370.     scsiCommand[2] = kSCReserved;
  371.     cmndSz             = 6;
  372.     
  373.     // Send the SCSI command to the device
  374.     
  375.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  376.     require(anErr == noErr, SendSCSICmndFails);
  377.  
  378.  
  379. /******* Clean-up *******/
  380.  
  381. SendSCSICmndFails:
  382.     return(anErr);
  383. }
  384. /* LaserSC_ResetDevice */
  385.  
  386.  
  387. /********************************************************************************************
  388.  
  389.                                         LaserSC_GetSenseData
  390.     function:
  391.                 LaserSC_GetSenseData returns the sense data for the printer which reflects the
  392.                 last "Check Condition" status. This call is useful to determine the current 
  393.                 state of the hardware and the result of the last executed command. A structure
  394.                 of type SCSenseData is returned which contains all state information
  395.                 available from the printer.
  396.                         
  397.     parameters:
  398.                 senseData            Pointer to a SCSenseData record in which to store the 
  399.                                         the current status information.
  400.     
  401.     returns:
  402.                 OSErr
  403.                     
  404. ********************************************************************************************/
  405. OSErr LaserSC_GetSenseData(SCSenseDataPtr senseData)
  406. {
  407.     OSErr        anErr;
  408.     short        scsiCommand[3];
  409.     long        cmndSz;
  410.     long        responseSz;
  411.     
  412.     // Validate the pointer parameter
  413.     check(senseData != nil);
  414.     
  415.     // Set up the request sense SCSI command to be sent to the printer
  416.     
  417.     scsiCommand[0] = kSCRequestSense;
  418.     scsiCommand[1] = kSCReserved;
  419.     scsiCommand[2] = sizeof(SCSenseData) << 8;        // High byte contains number of bytes to read
  420.     cmndSz             = 6;
  421.     
  422.     // Send the SCSI command to the device
  423.     
  424.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  425.     require(anErr == noErr, SendSCSICmndFails);
  426.  
  427.     // Now read the request sense data from the device
  428.     
  429.     responseSz = sizeof(SCSenseData);
  430.  
  431.     anErr = GetDataFromPrinter((Ptr) senseData, &responseSz, responseSz);
  432.     require(anErr == noErr, GetDataFromPrinterFails);
  433.     
  434.     
  435. /******* Cleanup *******/
  436.  
  437. GetDataFromPrinterFails:
  438. SendSCSICmndFails:
  439.     return(anErr);
  440. }
  441. /* LaserSC_GetSenseData */
  442.  
  443.  
  444. /********************************************************************************************
  445.  
  446.                                         LaserSC_SetPageMargins
  447.     function:
  448.                 LaserSC_SetPageMargins sets the page margins associated with the page buffer
  449.                 maintained by the printer. These margins should always be set when the printer
  450.                 is powered on in order to ensure that imaging doesn't occur off the paper.
  451.                 Imaging outside of the paper can reduce the life of the laser printing engine.
  452.                 These margins define the top and left margins of the imageable area of the page.
  453.                 
  454.                 This routine accepts two parameters, which represent the top margin and the
  455.                 left margin of the page. The top margin specifies the number of lines from 
  456.                 the top of the page, where each line is 1/300 of an inch. The top margin 
  457.                 should never be set to less that 0x76 or .197 inches. The left margin
  458.                 specifies the width of the left margin in bytes (byte = 8/300th inch). 
  459.                 Incrementing or decrementing this field by one adjusts the left margin by 
  460.                 8/300th inch. The left margin should not be set to less that .197 inches.
  461.                 
  462.                 To calculate the left margins for a new paper size, keep in mind the paper is
  463.                 fed into the printer center justified. This means if the width of the paper 
  464.                 decreases by .5 inches, the Left Margin would be increased by only .25 inches.
  465.                     
  466.     parameters:
  467.                 leftMargin            Left margin of the printer's page 
  468.                 topMargin            Top margin of the printer's page 
  469.     
  470.     returns:
  471.                 OSErr
  472.                     
  473. ********************************************************************************************/
  474. OSErr LaserSC_SetPageMargins(short leftMargin, short topMargin)
  475. {
  476.     OSErr            anErr;
  477.     short            scsiCommand[3];
  478.     long            cmndSz;
  479.     long            dataSz;
  480.     short            params[2];
  481.     
  482.     // Validate the parameters to ensure they aren't too small
  483.     check((topMargin >= kMinSCTopMargin) && (leftMargin >= kMinSCLeftMargin));
  484.     
  485.     // Set up the format SCSI command to be sent to the printer
  486.     
  487.     scsiCommand[0] = kSCFormatMargin;
  488.     scsiCommand[1] = kSCReserved;
  489.     scsiCommand[2] = 0x0400;                // High byte contains the length of the parameters being sent (4 = 2 * sizeof(short))
  490.     cmndSz             = 6;
  491.     
  492.     // Send the SCSI command to the device
  493.     
  494.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  495.     require(anErr == noErr, SendSCSICmndFails);
  496.  
  497.     // Send the parameters to the set margins command on to the device
  498.     
  499.     params[0]     = topMargin;        
  500.     params[1]     = leftMargin;
  501.     dataSz         = 4;
  502.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  503.     require(anErr == noErr, SendDataToPrinterFails);
  504.     
  505.     
  506. /******* Cleanup *******/
  507.  
  508. SendDataToPrinterFails:
  509. SendSCSICmndFails:
  510.     return(anErr);
  511. }
  512. /* LaserSC_SetPageMargins */
  513.  
  514.  
  515. /********************************************************************************************
  516.  
  517.                                         LaserSC_SetPageDimensions
  518.     function:
  519.                 LaserSC_SetPageDimensions sets the page dimensions associated with the page buffer
  520.                 maintained by the printer. These dimensions should always be set when the printer
  521.                 is powered on in order to ensure that imaging doesn't occur off the paper.
  522.                 Imaging outside of the paper can reduce the life of the laser printing engine.
  523.                 These dimensions define the number of lines per page and the number of bytes
  524.                 per line. 
  525.                 
  526.                 LaserSC_SetPageDimensions accepts two parameters, the number of bytes per line
  527.                 and the number of scan lines per page. The byes per line parameter specifies
  528.                 the width of the image in bytes, where each byte represents 8/300th of an
  529.                 inch (8 pixels). This parameter must be an even number and cannot be greater
  530.                 that 304. The number of scan lines per page parameter specifies the length
  531.                 of the image in lines, where each line represents 1/300th of an inch
  532.                 (1 pixel height).
  533.                 
  534.                 These two parameters define the dimensions of an image whose top left
  535.                 corner is assumed to start at coordinate (0, 0). Positive coordinates increase
  536.                 downward and to the right. All drawing will take place within the rectangle:
  537.                 (0, 0, (Bytes per line) * 8, Number of Lines).
  538.                 
  539.     parameters:
  540.                 bytesPerScanLine    Number of bytes within each line of the page 
  541.                 numScanLines        Number of lines within the page 
  542.     
  543.     returns:
  544.                 OSErr
  545.                     
  546. ********************************************************************************************/
  547. OSErr LaserSC_SetPageDimensions(short bytesPerScanLine, short numScanLines)
  548. {
  549.     OSErr        anErr;
  550.     short        scsiCommand[3];
  551.     long        cmndSz;
  552.     long        dataSz;
  553.     short        params[2];
  554.     
  555.     // Make sure the parameters are within tolerance
  556.     check(((bytesPerScanLine % 2) == 0) && (bytesPerScanLine <= kMaxRowBytes));
  557.     
  558.     // Set up the format SCSI command to be sent to the printer
  559.     
  560.     scsiCommand[0] = kSCFormatImage;
  561.     scsiCommand[1] = kSCReserved;
  562.     scsiCommand[2] = 0x0400;                // High byte contains the length of the parameters being sent (4 = 2 * sizeof(short))
  563.     cmndSz = 6;
  564.     
  565.     // Send the SCSI command to the device
  566.     
  567.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  568.     require(anErr == noErr, SendSCSICmndFails);
  569.     
  570.     // Send the parameters to the set dimensions command on to the device
  571.     
  572.     params[0]     = bytesPerScanLine;        
  573.     params[1]     = numScanLines;
  574.     dataSz         = 4;
  575.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  576.     require(anErr == noErr, SendDataToPrinterFails);
  577.  
  578.  
  579. /******* Cleanup *******/
  580.  
  581. SendDataToPrinterFails:
  582. SendSCSICmndFails:
  583.     return(anErr);
  584. }
  585. /* LaserSC_SetPageDimensions */
  586.  
  587.  
  588. /********************************************************************************************
  589.  
  590.                                         LaserSC_ClearBits
  591.     function:
  592.                 LaserSC_ClearBits will clear all bits inside the printers page buffer defined
  593.                 by the specified rectangle. This command only applies to printers with one 
  594.                 megabyte of RAM installed. If this command is issued with bufferred mode in 
  595.                 effect (see routine below), the clear command will return immediately, before
  596.                 clearing begins. While the area is being cleared, the printer will not be 
  597.                 able to accept SCSI comands and will return a Device Busy status when
  598.                 queried.
  599.                     
  600.     parameters:
  601.                 rectToClear            Rectangle within the page buffer to clear
  602.     
  603.     returns:
  604.                 OSErr
  605.                     
  606. ********************************************************************************************/
  607. OSErr LaserSC_ClearBits(Rect *rectToClear)
  608. {
  609.     OSErr        anErr;
  610.     short        scsiCommand[3];
  611.     long        cmndSz;
  612.     long        dataSz;
  613.     short        params[4];
  614.     
  615.     // Set up the clear bits SCSI command to be sent to the printer
  616.     
  617.     scsiCommand[0] = kSCClearBits;
  618.     scsiCommand[1] = kSCReserved;
  619.     scsiCommand[2] = 0x0800;                // High byte contains the length of the parameters being sent (8 = 4 * sizeof(short))
  620.     cmndSz             = 6;
  621.     
  622.     // Send the SCSI command to the device
  623.     
  624.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  625.     require(anErr == noErr, SendSCSICmndFails);
  626.     
  627.     // Send the parameters to the clear bits command on to the device
  628.     
  629.     params[0]     =     rectToClear->left;
  630.     params[1]     =     rectToClear->top;
  631.     params[2]     =     rectToClear->right;
  632.     params[3]     =     rectToClear->bottom;
  633.     dataSz         =     8;
  634.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  635.     require(anErr == noErr, SendDataToPrinterFails);
  636.  
  637.     // Now we must wait until the device is no longer busy
  638.     {
  639.         short        deviceStatus;        
  640.     
  641.         do
  642.         {
  643.             // Get the latest status info from the printer
  644.             
  645.             anErr = LaserSC_GetDeviceStatus(&deviceStatus);
  646.             require(anErr == noErr, LaserSC_GetDeviceStatusFails);
  647.             
  648.             // Let the client app have a chance to run
  649.             anErr = GXJobIdle();
  650.             require(anErr == noErr, JobIdleFails);
  651.         }
  652.         while (deviceStatus == kBusy);
  653.     }
  654.     
  655.  
  656. /******* Cleanup *******/
  657.  
  658. JobIdleFails:
  659. LaserSC_GetDeviceStatusFails:
  660. SendDataToPrinterFails:
  661. SendSCSICmndFails:
  662.     return(anErr);
  663. }
  664. /* LaserSC_ClearBits */
  665.  
  666.  
  667. /********************************************************************************************
  668.  
  669.                                         LaserSC_DrawBits
  670.     function:
  671.                     LaserSC_DrawBits transfers image data into the specified rectangular area of
  672.                     the printer's page buffer using one of several QuickDraw transfer modes. This
  673.                     command only applies to printers with one megabyte of RAM installed.
  674.                     
  675.                     The routine accepts three parameters which specify the image data to transfer,
  676.                     the rectangle within the printer's page buffer in which to image the data, 
  677.                     and one of the QuickDraw transfer modes: srcCopy, srcOR, srcXOR, or srcBIC.
  678.     
  679.     parameters:
  680.                     imageData            Pointer to the data to image
  681.                     rectToDrawIn        Pointer to rectangle in which to image the data
  682.                     qdTransferMode        One of the QuickDraw transfer modes srcCopy, srcOR, srcXOR,
  683.                                             or srcBIC
  684.     
  685.     returns:
  686.                     noErr                    Success
  687.                     badIISCParam        imageData pointer is nil
  688.                     badTransferMode    invalid transfer modes passed to 
  689.                     
  690.                     Any other error codes that can be returned by the Async I/O software                        
  691.  
  692.     called from:
  693.                     LaserIISC Interface Call
  694.                     
  695. ********************************************************************************************/
  696. OSErr LaserSC_DrawBits(Ptr imageData, Rect *rectToDrawIn, short numBytesPerLine, short qdTransferMode)
  697. {
  698.     OSErr                anErr;
  699.     short                scsiCommand[3];
  700.     long                cmndSz;
  701.     long                dataSz;
  702.     short                params[5];
  703.     long                numImageLines;
  704.     
  705.     // Initially validate the parameters 
  706.     
  707.     check((imageData != nil) && (rectToDrawIn != nil));
  708.     check((qdTransferMode == srcCopy)     ||
  709.             (qdTransferMode == srcOr)         ||
  710.             (qdTransferMode == srcXor)     ||
  711.             (qdTransferMode == srcBic));
  712.     
  713.     // Set up the draw bits SCSI command to be sent to the printer
  714.     
  715.     scsiCommand[0] = kSCDrawBits;
  716.     scsiCommand[1] = kSCReserved;
  717.     scsiCommand[2] = 0x0A00;                // High byte contains the length of the parameters being sent (10 = 4 * sizeof(short) + sizeof(short))
  718.     cmndSz             = 6;
  719.     
  720.     // Send the SCSI command to the device
  721.     
  722.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  723.     require(anErr == noErr, SendSCSICmndFails);
  724.     
  725.     // Now set up to send the rectangle to draw in and the transfer mode, and send it
  726.     
  727.     params[0]     =     rectToDrawIn->left;
  728.     params[1]     =     rectToDrawIn->top;
  729.     params[2]     =     rectToDrawIn->right;
  730.     params[3]     =     rectToDrawIn->bottom;
  731.     params[4]     =     qdTransferMode;
  732.     dataSz         =     10;
  733.     anErr = SendDataToPrinter((Ptr) params, dataSz, dataSz);
  734.     require(anErr == noErr, SendDataToPrinterFails1);
  735.     
  736.     // Now set up to pass the bit image to the draw bits command
  737.     
  738.     numImageLines = rectToDrawIn->bottom - rectToDrawIn->top;
  739.     dataSz = numImageLines * numBytesPerLine;
  740.  
  741.     // Now send the bitmap. We negate the last parameter to indicate the SCSI transfer should be a blind transfer.
  742.     // Also, the SCSI transfer chunk size is set to the number of bytes in 1 scan line
  743.     
  744.     anErr = SendDataToPrinter(imageData, dataSz, -(numBytesPerLine));
  745.     require(anErr == noErr, SendDataToPrinterFails2);
  746.  
  747.  
  748. /******* Cleanup *******/
  749.  
  750. SendDataToPrinterFails2:
  751. SendDataToPrinterFails1:
  752. SendSCSICmndFails:
  753.     return(anErr);
  754. }
  755. /* LaserSC_DrawBits */
  756.  
  757.  
  758. /********************************************************************************************
  759.  
  760.                                         LaserSC_PrintPage
  761.     function:
  762.                 LaserSC_PrintPage prints the current contents of the printer's page buffer.
  763.                 As soon as the SCSI print command returns control to this routine, it
  764.                 returns to the caller.  If the printer is set for buffered mode, then when
  765.                 this routine returns the printer may still be busy printing the page.  Thus,
  766.                 if you're using the printer in buffered mode, you must make sure that the
  767.                 printer is no longer busy before you start sending data for the next page.
  768.                 
  769.                 The continuousPrint parameter can be used to attain the 8 page per minute
  770.                 rating of the IISC engine. Set this parameter to true to attain the improved
  771.                 rating. It should only be set true if the next print command will be issued
  772.                 in less than 7.4 seconds (8.7 for Legal paper). 
  773.                 
  774.                 Setting clearPage to true causes the image area in the printers memory to be
  775.                 cleared as the page is being printed. This substantially reduces the amount
  776.                 of time a client may wait for the printers page buffer to clear.
  777.     
  778.     parameters:
  779.                 continuousPrint    T => print at 8 page per minute rate; F => print normal rate
  780.                 clearPage            T => clear printers page buffer while printing; F => don't clear buffer
  781.     
  782.     returns:
  783.                 OSErr
  784.                     
  785. ********************************************************************************************/
  786. OSErr LaserSC_PrintPage(Boolean    continuousPrint, Boolean clearPage) 
  787. {
  788.     OSErr            anErr;
  789.     short            scsiCommand[3];
  790.     long            cmndSz;
  791.  
  792.     // Set up the print command to be sent to the printer
  793.     
  794.     scsiCommand[0] = kSCPrint;
  795.     scsiCommand[1] = kSCReserved;
  796.     scsiCommand[2] = kSCReserved;
  797.     
  798.     if (continuousPrint)    // T => Modify command to indicate 8 page per minute printing
  799.         scsiCommand[2] += kPrintContinuous;
  800.         
  801.     if (clearPage)    // T => Clear page while we print
  802.         scsiCommand[2] += kClearWhilePrinting;
  803.     
  804.     scsiCommand[2] += kPrintFromSCRam;    //    Always print from the printers RAM
  805.     cmndSz = 6;
  806.         
  807.     // Send the SCSI command to the device
  808.     
  809.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  810.     require(anErr == noErr, SendSCSICmndFails);
  811.     
  812.     
  813. /******* Cleanup *******/
  814.  
  815. SendSCSICmndFails:
  816.     return(anErr);
  817. }
  818. /* LaserSC_PrintPage */
  819.  
  820.  
  821. /********************************************************************************************
  822.  
  823.                                         LaserSC_QueryPrinter
  824.     function:
  825.                 LaserSC_QueryPrinter returns specific information about the printer (e.g. paper
  826.                 size, vendor, etc.). This call is useful to determine configuration information
  827.                 about the printer. A structure of type SCInquiryData is returned which 
  828.                 contains all configuration information available from the printer.
  829.                         
  830.     parameters:
  831.                 inquiryData            Pointer to a SCInquiryData record in which to store the 
  832.                                         the configuration information.
  833.                 querySize            amount of data (bytes) that should be read from device
  834.  
  835.     returns:
  836.                 OSErr
  837.                     
  838. ********************************************************************************************/
  839. OSErr LaserSC_QueryPrinter(SCInquiryDataPtr inquiryData, char querySize)
  840. {
  841.     OSErr            anErr;
  842.     short            scsiCommand[3];
  843.     long            cmndSz;
  844.     long            dataSz;
  845.     
  846.     // Set up the inquiry command to be sent to the printer as the write portion
  847.     // of a status command.
  848.     
  849.     scsiCommand[0] = kSCInquiry;
  850.     scsiCommand[1] = kSCReserved;
  851.     scsiCommand[2] = querySize << 8;        // Number of inquiry bytes to return
  852.     cmndSz = 6;
  853.  
  854.     // Send the SCSI command to the device
  855.     
  856.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  857.     require(anErr == noErr, SendSCSICmndFails);
  858.     
  859.     // Now read the query data from the device
  860.     
  861.     dataSz = querySize;
  862.     
  863.     anErr = GetDataFromPrinter((Ptr) inquiryData, &dataSz, dataSz);
  864.     require(anErr == noErr, GetDataFromPrinterFails);
  865.  
  866.  
  867. /******* Cleanup *******/
  868.  
  869. GetDataFromPrinterFails:
  870. SendSCSICmndFails:
  871.     return(anErr);
  872. }/* LaserSC_QueryPrinter */
  873.  
  874.  
  875. /********************************************************************************************
  876.  
  877.                                         LaserSC_SetBuffandFeedMode
  878.     function:
  879.                 LaserSC_SetBuffandFeedMode is used to change the manual feed and bufferred mode
  880.                 settings of the printer. Setting manualFeed to true informs the printer that 
  881.                 paper will be fed manually as opposed to automatically from the cassette.
  882.                 Setting bufferedMode to true causes the print from printer RAM and clear bits
  883.                 commands to return immediately, without waiting for the command to complete.
  884.                 If buffered mode is selected, the printer will return a device busy status 
  885.                 while the operation completes.
  886.     
  887.     parameters:
  888.                 manualFeed        T => pages will be manually fed into the printer; F => cassette fed
  889.                 bufferedMode    T => Don't wait for clear bits and print RAM commands to complete;
  890.                                     F => wait for them to complete.
  891.                                         
  892.     returns:
  893.                 OSErr
  894.                     
  895. ********************************************************************************************/
  896. OSErr LaserSC_SetBuffandFeedMode(Boolean manualFeed, Boolean bufferedMode)
  897. {
  898.     OSErr        anErr;
  899.     short        scsiCommand[3];
  900.     long        cmndSz;
  901.     long        dataSz;
  902.     char        params[12];
  903.     short        i;
  904.     
  905.     // Set up the mode select SCSI command to be sent to the printer
  906.     
  907.     scsiCommand[0] = kSCModeSelect;
  908.     scsiCommand[1] = kSCReserved;
  909.     scsiCommand[2] = 0x0C00;            // High bytes specifies # of bytes being sent to the printer
  910.     cmndSz = 6;
  911.     
  912.     // Send the SCSI command to the device
  913.     
  914.     anErr = SendSCSICmnd((Ptr) scsiCommand, cmndSz);
  915.     require(anErr == noErr, SendSCSICmndFails);
  916.     
  917.     // Now set up the mode select parameters to be passed to the printer
  918.     
  919.     for (i = 0; i <= 11; i++)    //    Zero all twelve bytes initially
  920.         params[i] = 0;
  921.     
  922.     if (manualFeed)    // T => Set for manual feed mode
  923.         params[kFeed] = kManual;
  924.         
  925.     if (bufferedMode)    // T => Set for buffered mode
  926.         params[kBuffered] = kBufferedMode;
  927.     
  928.     // Now send the parameters to the printer
  929.     
  930.     dataSz = 12;
  931.     anErr = SendDataToPrinter(params, dataSz, dataSz);
  932.     require(anErr == noErr, SendDataToPrinterFails);
  933.     
  934. /******* CLean-up *******/
  935.  
  936. SendDataToPrinterFails:
  937. SendSCSICmndFails:
  938.     return(anErr);
  939. }
  940. /* LaserSC_SetBuffandFeedMode */
  941.  
  942.  
  943. /********************************************************************************************
  944.  
  945.                                         LaserSC_GetTimeoutForSCSICmnd
  946.     function:
  947.                     This routine returns the timeout that should be used in the call to SCSIComplete
  948.                     when the specified printer command is forced to complete.
  949.     
  950.     parameters:
  951.                     scsiCmnd        SCSI command to be issued to the printer (generated by another
  952.                                     LaserSCIntf.c interface routine).
  953.                     
  954.     returns:
  955.                     long            timeout (in ticks) to use for the SCSIComplete call
  956.                     
  957. ********************************************************************************************/
  958. long LaserSC_GetTimeoutForSCSICmnd(short scsiCmnd)
  959. {
  960.     long    timeout;
  961.     
  962.     switch ( scsiCmnd )
  963.     {
  964.          case kSCPrinterReady:
  965.          case kSCResetPrinter:
  966.          case kSCRequestSense:
  967.          case kSCFormatMargin:
  968.          case kSCFormatImage:
  969.          case kSCInquiry:
  970.          case kSCDrawBits:
  971.          case kSCModeSelect:
  972.          case kSCReserveUnit:
  973.          case kSCReleaseUnit:
  974.          case kSCModeSense:
  975.             timeout = 240;
  976.             break;
  977.             
  978.          case kSCClearBits:
  979.             timeout = 480;
  980.             break;
  981.             
  982.          case kSCDownLoadCode:
  983.          case kSCPrint:
  984.             timeout = 4800;
  985.             break;
  986.     }
  987.     
  988.     return(timeout);
  989. }
  990. /* LaserSC_GetTimeoutForSCSICmnd */
  991.